<template>
  <div class="layout">
    <div v-if="toolIsShow" class="layout-left" :style="{ width: widthLeftForTools + 'px' }">
      <a-tabs default-active-key="工具栏">
        <a-tab-pane class="tools-item-tab-panel" key="工具栏" tab="工具栏" force-render>
          <draggable v-for="widget in widgetTools" :key="widget.code" @end="evt => widgetOnDragged(evt, widget.code)">
            <div class="tools-item">
              <span class="tools-item-icon">
                <a-icon :type="widget.icon" />
              </span>
              <span class="tools-item-text">{{ widget.label }}</span>
            </div>
          </draggable>
          <a-collapse>
            <a-collapse-panel key="html" header="页面元素">
              <draggable v-for="widget in widgetTools.filter(item => {return item.type == 'html'})" :key="widget.code" @end="evt => widgetOnDragged(evt, widget.code)">
                <div class="tools-item">
                  <span class="tools-item-icon">
                    <a-icon :type="widget.icon" />
                  </span>
                  <span class="tools-item-text">{{ widget.label }}</span>
                </div>
              </draggable>
            </a-collapse-panel>
          </a-collapse>
        </a-tab-pane>
        <a-tab-pane class="tools-item-tab-panel" key="图层" tab="图层" force-render>
          <transition-group>
            <div v-for="(item, index) in layerWidget" :key="'item' + index" class="tools-item" :class="widgetIndex == index ? 'is-active' : ''" @click="layerClick(index)">
              <span class="tools-item-icon">
                <a-icon :type="item.icon" />
              </span>
              <span class="tools-item-text">{{ item.label }}</span>
            </div>
          </transition-group>
        </a-tab-pane>
      </a-tabs>
    </div>

    <div class="layout-left-fold" :style="{ width: widthLeftForToolsHideButton + 'px' }" @click="toolIsShow = !toolIsShow">
      <a-icon :type="toolIsShow ? 'double-left' : 'double-right'"/>
    </div>
    
    <div class="layout-middle" :style="{ width: middleWidth + 'px', height: middleHeight + 'px' }">
      <div class="top-button">
        <span class="btn">
          <a-tooltip title="保存">
            <a-icon type="save" style="font-size:18px;" @click="saveData"/>
          </a-tooltip>
        </span>
        <span class="btn">
          <a-tooltip title="预览">
            <a-icon type="eye" style="font-size:18px;" @click="viewScreen"/>
          </a-tooltip>
        </span>
        <span class="btn">
          <a-tooltip title="导入">
            <a-icon type="upload" style="font-size:18px;"/>
          </a-tooltip>
        </span>
        <span class="btn">
          <a-dropdown>
            <a-menu slot="overlay">
              <a-menu-item key="1">
                适合当前系统(包含数据集)
              </a-menu-item>
              <a-menu-item key="2">
                适合跨系统(不包含数据集)
              </a-menu-item>
            </a-menu>
            <a-tooltip title="导出">
              <a-icon type="download" style="font-size:18px;"/>
            </a-tooltip>
          </a-dropdown>
        </span>
      </div>
      <div class="workbench-container" :style="{ width: bigscreenWidthInWorkbench + 'px', height: bigscreenHeightInWorkbench + 'px'}" @mousedown="handleMouseDown">
        <vue-ruler-tool
          v-model="dashboard.presetLine"
          class="vueRuler"
          :step-length="50"
          :parent="true"
          :position="'relative'"
          :is-scale-revise="true"
          :visible.sync="dashboard.presetLineVisible"
        >
          <div
            ref="workbench"
            class="workbench"
            :style="{
              transform: workbenchTransform,
              width: bigscreenWidth + 'px',
              height: bigscreenHeight + 'px',
              'background-color': dashboard.backgroundColor,
              'background-image': 'url(' + dashboard.backgroundImage + ')',
              'background-position': '0% 0%',
              'background-size': '100% 100%',
              'background-repeat': 'initial',
              'background-attachment': 'initial',
              'background-origin': 'initial',
              'background-clip': 'initial'
            }"
            @click.self="setOptionsOnClickScreen"
          >
            <div v-if="grade" class="bg-grid"></div>
            <widget
              ref="widgets"
              v-for="(widget, index) in widgets"
              :key="index"
              v-model="widget.value"
              :index="index"
              :step="step"
              :type="widget.type"
              :bigscreen="{ bigscreenWidth, bigscreenHeight }"
              @onActivated="setOptionsOnClickWidget"
              @contextmenu.prevent.native="rightClick($event, index)"
              @mousedown.prevent.native="widgetsClick(index)"
              @mouseup.prevent.native="widgetsMouseup"
            />
          </div>
        </vue-ruler-tool>
      </div>
    </div>

    <div class="layout-right" :style="{ width: widthLeftForOptions + 'px' }">
      <a-tabs v-model="activeName" default-active-key="配置">
        <a-tab-pane key="配置" tab="配置" force-render v-if="(widgetOptions.setup && widgetOptions.setup.length > 0) || (widgetOptions.collapse && widgetOptions.collapse.length > 0)">
          <dynamicForm ref="formData" :options="widgetOptions.setup" @onChanged="val => widgetValueChanged('setup', val)"/>
        </a-tab-pane>
        <a-tab-pane key="数据" tab="数据" force-render v-if="widgetOptions.data && widgetOptions.data.length > 0">
          <dynamicForm ref="formData" :options="widgetOptions.data" @onChanged="val => widgetValueChanged('data', val)"/>
        </a-tab-pane>
        <a-tab-pane key="坐标" tab="坐标" force-render v-if="widgetOptions.position && widgetOptions.position.length > 0">
          <dynamicForm ref="formData" :options="widgetOptions.position" @onChanged="val => widgetValueChanged('position', val)"/>
        </a-tab-pane>
      </a-tabs>
    </div>

    <content-menu
      :visible.sync="visibleContentMenu"
      :style-obj="styleObj"
      @deletelayer="deletelayer"
      @copylayer="copylayer"
      @istopLayer="istopLayer"
      @setlowLayer="setlowLayer"
      @moveupLayer="moveupLayer"
      @movedownLayer="movedownLayer"
    />
  </div>
</template>

<script>
import { getAction, httpAction } from '@/api/manage'
import { cloneObject } from "@/utils/util"
import { widgetTools, getToolByCode } from "./tools/index";
import widget from "./widget/widget";
import dynamicForm from "./designerComponents/dynamicForm.vue";
import draggable from "vuedraggable";
import VueRulerTool from "vue-ruler-tool";
import contentMenu from "./designerComponents/contentMenu";

export default {
  name: "AjReportScreenDesignerIndex",
  components: {
    draggable,
    VueRulerTool,
    widget,
    dynamicForm,
    contentMenu
  },
  data() {
    return {
      uploadUrl: process.env.BASE_API + "/reportDashboard/import/" + this.$route.query.rcode,
      grade: false,
      layerWidget: [],
      widgetTools: widgetTools, // 左侧工具栏的组件图标，将js变量加入到当前作用域
      widthLeftForTools: 200, // 左侧工具栏宽度
      widthLeftForToolsHideButton: 15, // 左侧工具栏折叠按钮宽度
      widthLeftForOptions: 300, // 右侧属性配置区
      widthPaddingTools: 18,
      toolIsShow: true, // 左侧工具栏是否显示
      bigscreenWidth: 1920, // 大屏设计的大小
      bigscreenHeight: 1080,
      // 工作台大屏画布，保存到表gaea_report_dashboard中
      defaultDashboard: {
        id: null,
        title: "", // 大屏页面标题
        width: 1920, // 大屏设计宽度
        height: 1080, // 大屏设计高度
        backgroundColor: "", // 大屏背景色
        backgroundImage: "https://platform-kcyf-pds.oss-cn-beijing.aliyuncs.com/53bg.png", // 大屏背景图片
        refreshSeconds: null, // 大屏刷新时间间隔
        presetLine: [], // 辅助线
        presetLineVisible: true ,// 辅助线是否显示
        widgets: []
      },
      dashboard: {},
      // 大屏的标记
      screenCode: "",
      // 大屏画布中的组件
      widgets: [], // 工作区中拖放的组件

      // 当前激活组件
      widgetIndex: 0,
      // 当前激活组件右侧配置属性
      widgetOptions: {
        setup: [], // 配置
        data: [], // 数据
        position: [] // 坐标
      },
      flagWidgetClickStopPropagation: false, // 点击组件时阻止事件冒泡传递到画布click事件上
      styleObj: {
        left: 0,
        top: 0
      },
      visibleContentMenu: false,
      rightClickIndex: -1,
      activeName: "配置",
      url: {
        queryDashboardByRcode: '/ajreport/dashboard/queryByRcode',
        addDashboard: '/ajreport/dashboard/add',
        editDashboard: '/ajreport/dashboard/edit'
      }
    };
  },
  computed: {
    step () {
      return Number(100 / (this.bigscreenScaleInWorkbench * 100))
    },
    // 左侧折叠切换时，动态计算中间区的宽度
    middleWidth() {
      var widthLeftAndRight = 0;
      if (this.toolIsShow) {
        widthLeftAndRight += this.widthLeftForTools; // 左侧工具栏宽度
      }
      widthLeftAndRight += this.widthLeftForToolsHideButton; // 左侧工具栏折叠按钮宽度
      widthLeftAndRight += this.widthLeftForOptions; // 右侧配置栏宽度
      var middleWidth = document.body.clientWidth - widthLeftAndRight;
      return middleWidth;
    },
    middleHeight() {
      return document.body.clientHeight;
    },
    // 设计台按大屏的缩放比例
    bigscreenScaleInWorkbench() {
      var widthScale = (this.middleWidth - this.widthPaddingTools) / this.bigscreenWidth;
      var heightScale = (this.middleHeight - this.widthPaddingTools) / this.bigscreenHeight;
      return Math.min(widthScale, heightScale);
    },
    workbenchTransform() {
      return `scale(${this.bigscreenScaleInWorkbench}, ${this.bigscreenScaleInWorkbench})`;
    },
    // 大屏在设计模式的大小
    bigscreenWidthInWorkbench() {
      return this.getPXUnderScale(this.bigscreenWidth) + this.widthPaddingTools;
    },
    bigscreenHeightInWorkbench() {
      return this.getPXUnderScale(this.bigscreenHeight) + this.widthPaddingTools
    }
  },
  watch: {
    widgets: {
      handler(val) {
        this.handlerLayerWidget(val);
      },
      deep: true
    }
  },
  mounted() {
    // 如果是新的设计工作台
    this.initData();
    window.addEventListener("mouseup", () => {
      this.grade = false;
    });
  },
  methods: {
    widgetsToJson(widgets){
      return widgets.map(item => {
        item.options = JSON.parse(item.options)
        item.value = JSON.parse(item.value)
        return item
      })
    },
    initData() {
      const rcode = this.$route.query.rcode;
      if(rcode) {
        getAction(this.url.queryDashboardByRcode, {rcode: rcode}).then(res => {
          if(res.code == 200){
            console.log(res)
            this.dashboard = res.result
            if(res.result.widgets){
              this.widgets = this.widgetsToJson(res.result.widgets)
            }
          } else {
            this.dashboard = cloneObject(this.defaultDashboard)
            this.widgets = []
          }
          // 初始化完成后需选中设计面板
          this.setOptionsOnClickScreen();
        })
      } else {
        this.dashboard = cloneObject(this.defaultDashboard)
        this.widgets = []
        // 初始化完成后需选中设计面板
        this.setOptionsOnClickScreen();
      }
    },
    
    // 根据组件列表生成图层
    handlerLayerWidget(widgets) {
      this.layerWidget = widgets.map(item => {
        return {
          icon: getToolByCode(item.type).icon,
          label: item.value.setup.layerName
        }
      })
    },
    // 保存数据
    saveData() {
      if (!this.widgets || this.widgets.length == 0) {
        this.$message.error("请添加组件");
        return;
      }
      this.mathlayerZindex()
      this.dashboard.widgets = this.widgets
      let httpurl = ''
      let method = ''
      if (!this.dashboard.id) {
        httpurl += this.url.addDashboard
        method = 'post'
      } else {
        httpurl += this.url.editDashboard
        method = 'put'
      }
      const that = this
      httpAction(httpurl, this.dashboard, method).then((res) => {
        if (res.success) {
          that.$message.success(res.message)
          that.$emit('ok')
        } else {
          that.$message.warning(res.message)
        }
      })
    },
    // 预览
    viewScreen() {
      var router = this.$router.resolve({
        path: "/ajreport/report/screen/viewer/index",
        query: { rcode: this.$route.query.rcode }
      });
      window.open(router.href, "_blank");
    },
    // 导出
    exportDashboard(val) {
      
    },

    // 在缩放模式下的大小
    getPXUnderScale(px) {
      return this.bigscreenScaleInWorkbench * px;
    },

    // 拖动一个组件放到工作区中去，在拖动结束时，放到工作区对应的坐标点上去
    widgetOnDragged(evt, widgetCode) {
      console.log(evt, '事件对象')
      // 获取结束坐标和列名
      var eventX = evt.originalEvent.clientX; // 结束在屏幕的x坐标
      var eventY = evt.originalEvent.clientY; // 结束在屏幕的y坐标
      console.log(eventX, eventY, '鼠标落地点')
      var widgetTopInWorkbench = eventY - this.$refs.workbench.offsetTop;
      var widgetLeftInWorkbench = eventX - this.$refs.workbench.offsetLeft;

      // 计算在缩放模式下的x y
      var x = widgetLeftInWorkbench / this.bigscreenScaleInWorkbench;
      var y = widgetTopInWorkbench / this.bigscreenScaleInWorkbench;
      var tool = getToolByCode(widgetCode);
      var widgetJson = {
        type: widgetCode,
        value: {
          setup: {},
          data: {},
          position: {
            width: 0,
            height: 0,
            left: 0,
            top: 0,
            zIndex: 0
          }
        },
        options: tool.options
      }
      widgetJson.options.setup.forEach(item => {
        if(item.type != 'a-divider'){
          widgetJson.value.setup[item.name] = item.value
        }
      })
      widgetJson.options.position.forEach(item => {
        widgetJson.value.position[item.name] = item.value
      })
      if (widgetJson.options.data && widgetJson.options.data.length > 0) {
        widgetJson.options.data.forEach(item => {
          widgetJson.value.data[item.name] = item.value
        })
      }
      this.widgets.push(widgetJson);
      // 激活新组件的配置属性
      this.setOptionsOnClickWidget(this.widgets.length - 1);
    },
    layerClick(index) {
      this.widgetIndex = index;
      this.widgetsClick(index);
    },
    // 如果是点击大屏设计器中的底层，加载大屏底层属性
    setOptionsOnClickScreen() {
      this.screenCode = "screen";
      // 选中不同的组件 右侧都显示第一栏
      this.activeName = "配置";
      this.widgetOptions = getToolByCode("screen")["options"];
    },

    // 如果是点击某个组件，获取该组件的配置项
    setOptionsOnClickWidget(obj) {
      this.screenCode = "";
      if (typeof obj == "number") {
        this.widgetOptions = cloneObject(this.widgets[obj]["options"]);
        return;
      }
      if (obj.index < 0 || obj.index >= this.widgets.length) {
        return;
      }
      this.widgetIndex = obj.index;
      this.widgets[obj.index].value.position = obj;
      this.widgets[obj.index].options.position.forEach(el => {
        for (const key in obj) {
          if (el.name == key) {
            el.value = obj[key];
          }
        }
      });
      this.widgetOptions = cloneObject(this.widgets[obj.index]["options"]);
    },
    widgetsClick(index) {
      const draggableArr = this.$refs.widgets;
      for (let i = 0; i < draggableArr.length; i++) {
        if (i == index) {
          draggableArr[i].$refs.draggable.setActive(true);
        } else {
          draggableArr[i].$refs.draggable.setActive(false);
        }
      }
      this.setOptionsOnClickWidget(index);
      this.grade = true;
    },
    widgetsMouseup(e) {
      this.grade = false;
    },
    handleMouseDown() {
      const draggableArr = this.$refs.widgets;
      for (let i = 0; i < draggableArr.length; i++) {
        draggableArr[i].$refs.draggable.setActive(false);
      }
    },
    // 将当前选中的组件，右侧属性值更新
    widgetValueChanged(key, val) {
      if (this.screenCode == "screen") {
        this.dashboard = cloneObject(val);
      } else {
        for (let i = 0; i < this.widgets.length; i++) {
          if (this.widgetIndex == i) {
            this.widgets[i].value[key] = cloneObject(val);
            this.setDefaultValue(this.widgets[i].options[key], val);
          }
        }
      }
    },
    rightClick(event, index) {
      this.rightClickIndex = index;
      const left = event.clientX;
      const top = event.clientY;
      if (left || top) {
        this.styleObj = {
          left: left + "px",
          top: top + "px",
          display: "block"
        };
      }
      this.visibleContentMenu = true;
      return false;
    },
    setDefaultValue(options, val) {
      for (let i = 0; i < options.length; i++) {
        for (const k in val) {
          if (options[i].name == k) {
            options[i].value = val[k]
          }
        }
      }
    },
    mathlayerZindex(){
      this.widgets.forEach((item, index) => {
        item.sort = index
        item.options.position.filter(s => { return s.name == 'zIndex'})[0].value = index
        item.value.position.zIndex = index
      })
    },
    // 删除
    deletelayer() {
      this.widgets.splice(this.rightClickIndex, 1);
      this.$message.success('删除图层成功')
      this.mathlayerZindex()
    },
    // 复制
    copylayer() {
      const obj = cloneObject(this.widgets[this.rightClickIndex]);
      this.widgets.splice(this.widgets.length, 0, obj);
      this.mathlayerZindex()
    },
    // 置顶
    istopLayer() {
      if (this.rightClickIndex + 1 < this.widgets.length) {
        const temp = this.widgets.splice(this.rightClickIndex, 1)[0];
        this.widgets.push(temp);
        this.mathlayerZindex()
      }
    },
    // 置底
    setlowLayer() {
      if (this.rightClickIndex != 0) {
        this.widgets.unshift(this.widgets.splice(this.rightClickIndex, 1)[0]);
        this.mathlayerZindex()
      }
    },
    // 上移一层
    moveupLayer() {
      if (this.rightClickIndex != 0) {
        this.widgets[this.rightClickIndex] = this.widgets.splice(
          this.rightClickIndex - 1,
          1,
          this.widgets[this.rightClickIndex]
        )[0];
      } else {
        this.widgets.push(this.widgets.shift());
      }
      this.mathlayerZindex()
    },
    // 下移一层
    movedownLayer() {
      if (this.rightClickIndex != this.widgets.length - 1) {
        this.widgets[this.rightClickIndex] = this.widgets.splice(
          this.rightClickIndex + 1,
          1,
          this.widgets[this.rightClickIndex]
        )[0];
      } else {
        this.widgets.unshift(this.widgets.splice(this.rightClickIndex, 1)[0]);
      }
      this.mathlayerZindex()
    }
  }
};
</script>

<style scoped lang="less">
  
  .ant-tabs {
    color: #bfcbd9 !important;
  }
  .mr10 {
    margin-right: 10px;
  }

  .ml20 {
    margin-left: 20px;
  }

  .border-right {
    border-right: 1px solid #273b4d;
  }

  .border-left {
    border-left: 1px solid #273b4d;
  }

  .is-active {
    background: #31455d !important;
    color: #bfcbd9 !important;
  }

  .layout {
    display: -webkit-box;
    display: -ms-flexbox;
    display: flex;
    width: 100%;
    height: 100%;
    -webkit-box-sizing: border-box;
    box-sizing: border-box;
    overflow: hidden;

    .layout-left {
      display: inline-block;
      height: 100%;
      box-sizing: border-box;
      -webkit-box-sizing: border-box;
      border: 0px;
      background-color: #263445;
      .tools-item-tab-panel {
        height: calc(100vh - 66px);
        overflow-x: hidden;
        overflow-y: auto;
      }
      //工具栏一个元素
      .tools-item {
        display: flex;
        position: relative;
        width: 100%;
        height: 48px;
        align-items: center;
        -webkit-box-align: center;
        padding: 0 6px;
        cursor: pointer;
        font-size: 12px;
        margin-bottom: 1px;

        .tools-item-icon {
          color: #409eff;
          margin-right: 10px;
          width: 53px;
          height: 30px;
          line-height: 30px;
          text-align: center;
          display: block;
          border: 1px solid #3a4659;
          background: #282a30;
        }

        .tools-item-text {
        }
      }
    }

    .layout-left-fold {
      display: -webkit-box;
      display: -ms-flexbox;
      display: flex;
      height: 100%;

      font-size: 12px;
      overflow: hidden;
      background-color: #242a30;
      cursor: pointer;
      padding-top: 26%;

      i {
        font-size: 18px;
        width: 18px;
        height: 23px;
        margin-left: 0px;
        color: #bfcbd9;
      }
    }

    .layout-middle {
      // display: flex;
      position: relative;
      //width: calc(100% - 445px);
      height: 100%;
      background-color: rgb(36, 42, 48);
      box-sizing: border-box;
      -webkit-box-sizing: border-box;
      border: 1px solid rgb(36, 42, 48);
      align-items: center;
      vertical-align: middle;
      text-align: center;
      
      .top-button {
        display: flex;
        flex-direction: row;
        height: 40px;
        line-height: 40px;
        margin-left: 9px;
      
        .btn {
          color: #788994;
          width: 55px;
          text-align: center;
          display: block;
          cursor: pointer;
      
          &:hover {
            background: rgb(25, 29, 34);
          }
        }
      }

      .workbench-container {
        position: relative;
        -webkit-transform-origin: 0 0;
        transform-origin: 0 0;
        -webkit-box-sizing: border-box;
        box-sizing: border-box;
        margin: 0;
        padding: 0;

        .vueRuler {
          width: 100%;
          padding: 18px 0px 0px 18px;
        }

        .workbench {
          background-color: #1e1e1e;
          position: relative;
          -webkit-user-select: none;
          -moz-user-select: none;
          -ms-user-select: none;
          user-select: none;
          -webkit-transform-origin: 0 0;
          transform-origin: 0 0;
          margin: 0;
          padding: 0;
        }

        .bg-grid {
          position: absolute;
          top: 0;
          left: 0;
          width: 100%;
          height: 100%;
          background-size: 30px 30px, 30px 30px;
          background-image: linear-gradient(
              hsla(0, 0%, 100%, 0.1) 1px,
              transparent 0
            ),
            linear-gradient(90deg, hsla(0, 0%, 100%, 0.1) 1px, transparent 0);
          // z-index: 2;
        }
      }

      .bottom-text {
        width: 100%;
        color: #a0a0a0;
        font-size: 16px;
        position: absolute;
        bottom: 20px;
      }
    }

    .layout-right {
      display: inline-block;
      height: 100%;
    }
  }
</style>
